﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using VDS.RDF;
using VDS.RDF.Storage;
using VDS.RDF.Query;
using System.Configuration;
using System.Data;
using LCMS_MVC.Models;

namespace LCMS_MVC.Models
{
    public class TriplesModel
    {
        private string _graphUri;
        private VirtuosoManager _manager;
        public string _outputText;

        private const String VirtuosoQuadStoreDB = "DB";

        string username = ConfigurationManager.AppSettings["VirtuosoUsername"];
        string password = ConfigurationManager.AppSettings["VirtuosoPassword"];
        string server = ConfigurationManager.AppSettings["VirtuosoServer"];
        int port = Int32.Parse(ConfigurationManager.AppSettings["VirtuosoPort"]);

        public TriplesModel()
        {
            this._manager = new VirtuosoManager(server, port, VirtuosoQuadStoreDB, username, password);
            this._graphUri = "http://vcei.towson.edu/LCMS/LO";    
        }

        public enum triplesUpdateTypes{Insert, Update, Delete};
        
        public void TriplesFactory(LORegistrationModel LearningObject)
        {

            Graph g = new Graph();
            this._manager.LoadGraph(g, "http://vcei.towson.edu/LCMS/LO");
            if (!g.IsEmpty)
            {
                //
                try
                {
                    //setting the identifier here which is slightly different from the rest of our model because we have to get the current highest identifier
                    //and then add 1 to create next sequential identifier
                    string highestCurrentIdentifier = GetHighestCurrentIdentifier();
                    int highestCurrentIdentifierInt;
                    int.TryParse(highestCurrentIdentifier, out highestCurrentIdentifierInt);

                    if (highestCurrentIdentifierInt > 0)
                    {
                        highestCurrentIdentifierInt++;
                    }
                    else 
                    { 
                        highestCurrentIdentifierInt = 1; 
                    }

                    IUriNode loIdentifierSubject = g.CreateUriNode(new Uri(g.BaseUri + "/" + highestCurrentIdentifierInt.ToString()));
                    IUriNode loIdentifierPredicate = g.CreateUriNode(new Uri(g.BaseUri + "/LO.owl#identifier"));
                    ILiteralNode loIdentifierObject = g.CreateLiteralNode(highestCurrentIdentifierInt.ToString());

                    g.Assert(loIdentifierSubject, loIdentifierPredicate, loIdentifierObject);

                    #region General
                    
                    if (!String.IsNullOrEmpty(LearningObject.Title))
                    {
                        IUriNode loTitleSubject = g.CreateUriNode(new Uri(g.BaseUri + "/" + highestCurrentIdentifierInt.ToString()));
                        IUriNode loTitlePredicate = g.CreateUriNode(new Uri(g.BaseUri + "/LO.owl#title"));
                        ILiteralNode loTitleObject = g.CreateLiteralNode(LearningObject.Title);

                        g.Assert(loTitleSubject, loTitlePredicate, loTitleObject);
                    }
                    if (!String.IsNullOrEmpty(LearningObject.Description))
                    {
                        IUriNode loDescriptionSubject = g.CreateUriNode(new Uri(g.BaseUri + "/" + highestCurrentIdentifierInt.ToString()));
                        IUriNode loDescriptionPredicate = g.CreateUriNode(new Uri(g.BaseUri + "/LO.owl#description"));
                        ILiteralNode loDescriptionObject = g.CreateLiteralNode(LearningObject.Description);

                        g.Assert(loDescriptionSubject, loDescriptionPredicate, loDescriptionObject);
                    }
                    if (!String.IsNullOrEmpty(LearningObject.KeywordSubject))
                    {
                        IUriNode loKeywordSubjectSubject = g.CreateUriNode(new Uri(g.BaseUri + "/" + highestCurrentIdentifierInt.ToString()));
                        IUriNode loKeywordSubjectPredicate = g.CreateUriNode(new Uri(g.BaseUri + "/LO.owl#keywordSubject"));
                        ILiteralNode loKeywordSubjectObject = g.CreateLiteralNode(LearningObject.KeywordSubject);

                        g.Assert(loKeywordSubjectSubject, loKeywordSubjectPredicate, loKeywordSubjectObject);
                    }
                    if (!String.IsNullOrEmpty(LearningObject.Language))
                    {
                        IUriNode loLanguageSubject = g.CreateUriNode(new Uri(g.BaseUri + "/" + highestCurrentIdentifierInt.ToString()));
                        IUriNode loLanguagePredicate = g.CreateUriNode(new Uri(g.BaseUri + "/LO.owl#language"));
                        ILiteralNode loLanguageObject = g.CreateLiteralNode(LearningObject.Language);

                        g.Assert(loLanguageSubject, loLanguagePredicate, loLanguageObject);
                    }
                    if (!String.IsNullOrEmpty(LearningObject.CreatorFirstName))
                    {
                        IUriNode loCreatorFirstNameSubject = g.CreateUriNode(new Uri(g.BaseUri + "/" + highestCurrentIdentifierInt.ToString()));
                        IUriNode loCreatorFirstNamePredicate = g.CreateUriNode(new Uri(g.BaseUri + "/LO.owl#creatorFirstName"));
                        ILiteralNode loCreatorFirstNameObject = g.CreateLiteralNode(LearningObject.CreatorFirstName);

                        g.Assert(loCreatorFirstNameSubject, loCreatorFirstNamePredicate, loCreatorFirstNameObject);
                    }
                    if (!String.IsNullOrEmpty(LearningObject.CreatorLastName))
                    {
                        IUriNode loCreatorLastNameSubject = g.CreateUriNode(new Uri(g.BaseUri + "/" + highestCurrentIdentifierInt.ToString()));
                        IUriNode loCreatorLastNamePredicate = g.CreateUriNode(new Uri(g.BaseUri + "/LO.owl#creatorLastName"));
                        ILiteralNode loCreatorLastNameObject = g.CreateLiteralNode(LearningObject.CreatorLastName);

                        g.Assert(loCreatorLastNameSubject, loCreatorLastNamePredicate, loCreatorLastNameObject);
                    }
                    if (!String.IsNullOrEmpty(LearningObject.CreatorEmail))
                    {
                        IUriNode loCreatorEmailSubject = g.CreateUriNode(new Uri(g.BaseUri + "/" + highestCurrentIdentifierInt.ToString()));
                        IUriNode loCreatorEmailPredicate = g.CreateUriNode(new Uri(g.BaseUri + "/LO.owl#creatorEmail"));
                        ILiteralNode loCreatorEmailObject = g.CreateLiteralNode(LearningObject.CreatorEmail);

                        g.Assert(loCreatorEmailSubject, loCreatorEmailPredicate, loCreatorEmailObject);
                    }

                    #endregion General

                    #region LifeCycle
                    if (!String.IsNullOrEmpty(LearningObject.Version))
                    {
                        IUriNode loVersionSubject = g.CreateUriNode(new Uri(g.BaseUri + "/" + highestCurrentIdentifierInt.ToString()));
                        IUriNode loVersionPredicate = g.CreateUriNode(new Uri(g.BaseUri + "/LO.owl#version")); 
                        ILiteralNode loVersionObject = g.CreateLiteralNode(LearningObject.Version);

                        g.Assert(loVersionSubject, loVersionPredicate, loVersionObject);
                    }
                    if (!String.IsNullOrEmpty(LearningObject.Status))
                    {
                        IUriNode loStatusSubject = g.CreateUriNode(new Uri(g.BaseUri + "/" + highestCurrentIdentifierInt.ToString()));
                        IUriNode loStatusPredicate = g.CreateUriNode(new Uri(g.BaseUri + "/LO.owl#status"));
                        ILiteralNode loStatusObject = g.CreateLiteralNode(LearningObject.Status);

                        g.Assert(loStatusSubject, loStatusPredicate, loStatusObject);
                    }
                    if (!String.IsNullOrEmpty(LearningObject.Date))
                    {
                        IUriNode loDateSubject = g.CreateUriNode(new Uri(g.BaseUri + "/" + highestCurrentIdentifierInt.ToString()));
                        IUriNode loDatePredicate = g.CreateUriNode(new Uri(g.BaseUri + "/LO.owl#date"));
                        ILiteralNode loDateObject = g.CreateLiteralNode(LearningObject.Date);

                        g.Assert(loDateSubject, loDatePredicate, loDateObject);
                    }
                    if (!String.IsNullOrEmpty(LearningObject.Provenance))
                    {
                        IUriNode loProvenanceSubject = g.CreateUriNode(new Uri(g.BaseUri + "/" + highestCurrentIdentifierInt.ToString()));
                        IUriNode loProvenancePredicate = g.CreateUriNode(new Uri(g.BaseUri + "/LO.owl#provenance"));
                        ILiteralNode loProvenanceObject = g.CreateLiteralNode(LearningObject.Provenance);

                        g.Assert(loProvenanceSubject, loProvenancePredicate, loProvenanceObject);
                    }
                    if (!String.IsNullOrEmpty(LearningObject.Contributor))
                    {
                        IUriNode loContributorSubject = g.CreateUriNode(new Uri(g.BaseUri + "/" + highestCurrentIdentifierInt.ToString()));
                        IUriNode loContributorPredicate = g.CreateUriNode(new Uri(g.BaseUri + "/LO.owl#contributor"));
                        ILiteralNode loContributorObject = g.CreateLiteralNode(LearningObject.Contributor);

                        g.Assert(loContributorSubject, loContributorPredicate, loContributorObject);
                    }
                    #endregion LifeCycle

                    #region Rights
                    if (!String.IsNullOrEmpty(LearningObject.Rightsholder))
                    {
                        IUriNode loRightsholderSubject = g.CreateUriNode(new Uri(g.BaseUri + "/" + highestCurrentIdentifierInt.ToString()));
                        IUriNode loRightsholderPredicate = g.CreateUriNode(new Uri(g.BaseUri + "/LO.owl#rightsholder"));
                        ILiteralNode loRightsholderObject = g.CreateLiteralNode(LearningObject.Rightsholder);

                        g.Assert(loRightsholderSubject, loRightsholderPredicate, loRightsholderObject);
                    }
                    if (!String.IsNullOrEmpty(LearningObject.Cost))
                    {
                        IUriNode loCostSubject = g.CreateUriNode(new Uri(g.BaseUri + "/" + highestCurrentIdentifierInt.ToString()));
                        IUriNode loCostPredicate = g.CreateUriNode(new Uri(g.BaseUri + "/LO.owl#cost"));
                        ILiteralNode loCostObject = g.CreateLiteralNode(LearningObject.Cost);

                        g.Assert(loCostSubject, loCostPredicate, loCostObject);
                    }
                    if (!String.IsNullOrEmpty(LearningObject.CopyrightOtherRestrictions))
                    {
                        IUriNode loCopyrightOtherRestrictionsSubject = g.CreateUriNode(new Uri(g.BaseUri + "/" + highestCurrentIdentifierInt.ToString()));
                        IUriNode loCopyrightOtherRestrictionsPredicate = g.CreateUriNode(new Uri(g.BaseUri + "/LO.owl#copyrightAndOtherRestrictions"));
                        ILiteralNode loCopyrightOtherRestrictionsObject = g.CreateLiteralNode(LearningObject.CopyrightOtherRestrictions);

                        g.Assert(loCopyrightOtherRestrictionsSubject, loCopyrightOtherRestrictionsPredicate, loCopyrightOtherRestrictionsObject);
                    }
                    if (!String.IsNullOrEmpty(LearningObject.RightsDescription))
                    {
                        IUriNode loRightsDescriptionSubject = g.CreateUriNode(new Uri(g.BaseUri + "/" + highestCurrentIdentifierInt.ToString()));
                        IUriNode loRightsDescriptionPredicate = g.CreateUriNode(new Uri(g.BaseUri + "/LO.owl#rightsDescription"));
                        ILiteralNode loRightsDescriptionObject = g.CreateLiteralNode(LearningObject.RightsDescription);

                        g.Assert(loRightsDescriptionSubject, loRightsDescriptionPredicate, loRightsDescriptionObject);
                    }

                    #endregion Rights

                    #region Technical
                    if (!String.IsNullOrEmpty(LearningObject.Format))
                    {
                        IUriNode loFormatSubject = g.CreateUriNode(new Uri(g.BaseUri + "/" + highestCurrentIdentifierInt.ToString()));
                        IUriNode loFormatPredicate = g.CreateUriNode(new Uri(g.BaseUri + "/LO.owl#format"));
                        ILiteralNode loFormatObject = g.CreateLiteralNode(LearningObject.Format);

                        g.Assert(loFormatSubject, loFormatPredicate, loFormatObject);
                    }
                    if (!String.IsNullOrEmpty(LearningObject.Size))
                    {
                        IUriNode loSizeSubject = g.CreateUriNode(new Uri(g.BaseUri + "/" + highestCurrentIdentifierInt.ToString()));
                        IUriNode loSizePredicate = g.CreateUriNode(new Uri(g.BaseUri + "/LO.owl#size"));
                        ILiteralNode loSizeObject = g.CreateLiteralNode(LearningObject.Size);

                        g.Assert(loSizeSubject, loSizePredicate, loSizeObject);
                    }
                    if (!String.IsNullOrEmpty(LearningObject.Location))
                    {
                        IUriNode loLocationSubject = g.CreateUriNode(new Uri(g.BaseUri + "/" + highestCurrentIdentifierInt.ToString()));
                        IUriNode loLocationPredicate = g.CreateUriNode(new Uri(g.BaseUri + "/LO.owl#location"));
                        ILiteralNode loLocationObject = g.CreateLiteralNode(LearningObject.Location);

                        g.Assert(loLocationSubject, loLocationPredicate, loLocationObject);
                    }
                    if (!String.IsNullOrEmpty(LearningObject.InstallationRemark))
                    {
                        IUriNode loInstallationRemarkSubject = g.CreateUriNode(new Uri(g.BaseUri + "/" + highestCurrentIdentifierInt.ToString()));
                        IUriNode loInstallationRemarkPredicate = g.CreateUriNode(new Uri(g.BaseUri + "/LO.owl#installationRemarks"));
                        ILiteralNode loInstallationRemarkObject = g.CreateLiteralNode(LearningObject.InstallationRemark);

                        g.Assert(loInstallationRemarkSubject, loInstallationRemarkPredicate, loInstallationRemarkObject);
                    }
                    if (!String.IsNullOrEmpty(LearningObject.PlatformRequirements))
                    {
                        IUriNode loPlatformRequirementsSubject = g.CreateUriNode(new Uri(g.BaseUri + "/" + highestCurrentIdentifierInt.ToString()));
                        IUriNode loPlatformRequirementsPredicate = g.CreateUriNode(new Uri(g.BaseUri + "/LO.owl#platformRequirements"));
                        ILiteralNode loPlatformRequirementsObject = g.CreateLiteralNode(LearningObject.PlatformRequirements);

                        g.Assert(loPlatformRequirementsSubject, loPlatformRequirementsPredicate, loPlatformRequirementsObject);
                    }
                    if (!String.IsNullOrEmpty(LearningObject.Duration))
                    {
                        IUriNode loDurationSubject = g.CreateUriNode(new Uri(g.BaseUri + "/" + highestCurrentIdentifierInt.ToString()));
                        IUriNode loDurationPredicate = g.CreateUriNode(new Uri(g.BaseUri + "/LO.owl#duration"));
                        ILiteralNode loDurationObject = g.CreateLiteralNode(LearningObject.Duration);

                        g.Assert(loDurationSubject, loDurationPredicate, loDurationObject);
                    }
                    #endregion Technical

                    #region Relation
                    if (!String.IsNullOrEmpty(LearningObject.Relation))
                    {
                        IUriNode loRelationSubject = g.CreateUriNode(new Uri(g.BaseUri + "/" + highestCurrentIdentifierInt.ToString()));
                        IUriNode loRelationPredicate = g.CreateUriNode(new Uri(g.BaseUri + "/LO.owl#relation"));
                        IBlankNode loRelationObject = g.CreateBlankNode();

                        g.Assert(loRelationSubject, loRelationPredicate, loRelationObject);
                    }
                    if (!String.IsNullOrEmpty(LearningObject.RelationDescription))
                    {
                        IUriNode loRelationDescriptionSubject = g.CreateUriNode(new Uri(g.BaseUri + "/" + highestCurrentIdentifierInt.ToString()));
                        IUriNode loRelationDescriptionPredicate = g.CreateUriNode(new Uri(g.BaseUri + "/LO.owl#relationDescription"));
                        IBlankNode loRelationDescriptionObject = g.CreateBlankNode();

                        g.Assert(loRelationDescriptionSubject, loRelationDescriptionPredicate, loRelationDescriptionObject);
                    }
                    if (!String.IsNullOrEmpty(LearningObject.Source))
                    {
                        IUriNode loSourceSubject = g.CreateUriNode(new Uri(g.BaseUri + "/" + highestCurrentIdentifierInt.ToString()));
                        IUriNode loSourcePredicate = g.CreateUriNode(new Uri(g.BaseUri + "/LO.owl#source"));
                        IBlankNode loSourceObject = g.CreateBlankNode();

                        g.Assert(loSourceSubject, loSourcePredicate, loSourceObject);
                    }
                    if (!String.IsNullOrEmpty(LearningObject.LearningResourceType))
                    {
                        IUriNode loLearningResourceTypeSubject = g.CreateUriNode(new Uri(g.BaseUri + "/" + highestCurrentIdentifierInt.ToString()));
                        IUriNode loLearningResourceTypePredicate = g.CreateUriNode(new Uri(g.BaseUri + "/LO.owl#learningResourceType"));
                        ILiteralNode loLearningResourceTypeObject = g.CreateLiteralNode(LearningObject.LearningResourceType);

                        g.Assert(loLearningResourceTypeSubject, loLearningResourceTypePredicate, loLearningResourceTypeObject);
                    }
                    #endregion Relation

                    #region Educational
                    if (!String.IsNullOrEmpty(LearningObject.Size))
                    {
                        IUriNode loSizeSubject = g.CreateUriNode(new Uri(g.BaseUri + "/" + highestCurrentIdentifierInt.ToString()));
                        IUriNode loSizePredicate = g.CreateUriNode(new Uri(g.BaseUri + "/LO.owl#size"));
                        ILiteralNode loSizeObject = g.CreateLiteralNode(LearningObject.Size);

                        g.Assert(loSizeSubject, loSizePredicate, loSizeObject);
                    }
                    if (!String.IsNullOrEmpty(LearningObject.Difficulty))
                    {
                        IUriNode loDifficultySubject = g.CreateUriNode(new Uri(g.BaseUri + "/" + highestCurrentIdentifierInt.ToString()));
                        IUriNode loDifficultyPredicate = g.CreateUriNode(new Uri(g.BaseUri + "/LO.owl#difficulty"));
                        ILiteralNode loDifficultyObject = g.CreateLiteralNode(LearningObject.Difficulty);

                        g.Assert(loDifficultySubject, loDifficultyPredicate, loDifficultyObject);
                    }
                    if (!String.IsNullOrEmpty(LearningObject.TypicalLearningTime))
                    {
                        IUriNode loTypicalLearningTimeSubject = g.CreateUriNode(new Uri(g.BaseUri + "/" + highestCurrentIdentifierInt.ToString()));
                        IUriNode loTypicalLearningTimePredicate = g.CreateUriNode(new Uri(g.BaseUri + "/LO.owl#typicalLearningTime"));
                        ILiteralNode loTypicalLearningTimeObject = g.CreateLiteralNode(LearningObject.TypicalLearningTime);

                        g.Assert(loTypicalLearningTimeSubject, loTypicalLearningTimePredicate, loTypicalLearningTimeObject);
                    }
                    if (!String.IsNullOrEmpty(LearningObject.Audience))
                    {
                        IUriNode loAudienceSubject = g.CreateUriNode(new Uri(g.BaseUri + "/" + highestCurrentIdentifierInt.ToString()));
                        IUriNode loAudiencePredicate = g.CreateUriNode(new Uri(g.BaseUri + "/LO.owl#audience"));
                        ILiteralNode loAudienceObject = g.CreateLiteralNode(LearningObject.Audience);

                        g.Assert(loAudienceSubject, loAudiencePredicate, loAudienceObject);
                    }
                    if (!String.IsNullOrEmpty(LearningObject.NoOfPages))
                    {
                        IUriNode loNoOfPagesSubject = g.CreateUriNode(new Uri(g.BaseUri + "/" + highestCurrentIdentifierInt.ToString()));
                        IUriNode loNoOfPagesPredicate = g.CreateUriNode(new Uri(g.BaseUri + "LO.owl#noOfPages"));
                        ILiteralNode loNoOfPagesObject = g.CreateLiteralNode(LearningObject.NoOfPages);

                        g.Assert(loNoOfPagesSubject, loNoOfPagesPredicate, loNoOfPagesObject);
                    }
                    #endregion Educational

                    this._manager.SaveGraph(g);
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.Message + "-" + e.StackTrace);
                }
            }
            else
            {
                throw new System.InvalidOperationException("Graph was empty -- not a valid string uri for graph");
            }

        }

        //test method
        public void InsertIntoGraph()
        {
            Graph g = new Graph();
            this._manager.LoadGraph(g, "http://vcei.towson.edu/LCMS/LO");
            if (!g.IsEmpty)
            {
                //
                try
                {
                    IUriNode loSubject = g.CreateUriNode(new Uri(g.BaseUri + "/7"));
                    IUriNode loPredicate = g.CreateUriNode(new Uri(g.BaseUri + "/LO.owl#identifier"));
                    ILiteralNode loObject = g.CreateLiteralNode("7");
                    g.Assert(loSubject, loPredicate, loObject);

                    IUriNode lo2Subject = g.CreateUriNode(new Uri(g.BaseUri + "/8"));
                    IUriNode lo2Predicate = g.CreateUriNode(new Uri(g.BaseUri + "/LO.owl#identifier"));
                    ILiteralNode lo2Object = g.CreateLiteralNode("7");
                    g.Assert(lo2Subject, lo2Predicate, lo2Object);
                    this._manager.SaveGraph(g);
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.Message + "-" + e.StackTrace);
                }
            }
            else
            {
                throw new System.InvalidOperationException("Graph was empty -- not a valid string uri for graph");
            }
            
        }

        public string GetHighestCurrentIdentifier()
        {
            //setting up our parameterized query to get the highest current identifier used in our graph
            SparqlParameterizedString queryStr = new SparqlParameterizedString();
            queryStr.Namespaces.AddNamespace("LCMS", new Uri("http://vcei.towson.edu/LCMS/LO/LO.owl#"));

            queryStr.CommandText = "SELECT ?o WHERE { ?s LCMS:identifier ?o } ";
            System.Diagnostics.Debug.WriteLine(queryStr.ToString());
            Object results = this._manager.Query(queryStr.ToString());
            var topIdentifier = "";
            if (results is SparqlResultSet) 
            {
                //create a new list of unique identifiers to look at, order by descending,
                //pull highest num so we know what the next identifier should be
                List<string> identifiersList = new List<string>();
                SparqlResultSet rset = (SparqlResultSet)results;
                foreach (SparqlResult result in rset)
                {
                    string idNum = result.ToString();
                    string idNumParsed = idNum.Replace("?o = ", "");
                    
                    identifiersList.Add(idNumParsed);

                }

                topIdentifier = identifiersList.Max();

            }

            return topIdentifier;
             
        }
    }
}